/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package linkeddata.arida.ufc.br.manager.impl;

import java.io.File;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import linkeddata.arida.ufc.br.enums.ClausesSparql;
import linkeddata.arida.ufc.br.manager.SparqlQuery;
import linkeddata.arida.ufc.br.util.TripleStore;
import linkeddata.arida.ufc.br.xml.JDOMPrefixes;
import linkeddata.arida.ufc.br.xml.TripleXML;
import org.semanticweb.owlapi.model.OWLOntology;
import org.semanticweb.owlapi.model.OWLOntologyCreationException;
import org.semanticweb.owlapi.reasoner.OWLReasoner;
import org.semanticweb.owlapi.util.DefaultPrefixManager;

/**
 *
 * @author jeovane
 */
public class BuildsSparqlQuery extends BuildsHierarchyDataProperty implements SparqlQuery {

    private BuildsSparqlQueryAux queryAux;
    private JDOMPrefixes jPrefixes;
    private String getPrefixes = "";

    public BuildsSparqlQuery(OWLOntology ontology, DefaultPrefixManager pm, OWLReasoner reasoner, File file) {
        super(ontology, reasoner, pm);
        queryAux = new BuildsSparqlQueryAux(ontology, reasoner, pm);
        jPrefixes = new JDOMPrefixes(file);
    }

    @Override
    public String buildsSelect(String jsonTextQuery, String activeUnion) throws OWLOntologyCreationException {
        for (Map.Entry entry : jPrefixes.getPrefixesForXML().entrySet()) {
            getPrefixes += entry.getKey() + " " + entry.getValue() + "\n";
        }
        setQuery(getPrefixes);

        // Adiciona a cláusula SELECT na consulta
        setQuery(getQuery() + "\n" + ClausesSparql.SELECT.toString());

        for (String keys : queryAux.classHierarchyKey(jsonTextQuery)) {
            setArrayKeysMap(keys);
            for (String value : queryAux.classHierarchyValue(jsonTextQuery, keys)) {
                setSetSelect(" ?" + keys + "_" + value);
            }
        }

        for (String varSelect : getSetSelect()) {
            setQuery(getQuery() + "" + varSelect);
        }

        return getQuery();
    }

    @Override
    public String buildsWhere(String jsonTextQuery, String jsonTextOptional, Set<String> setFilter) throws OWLOntologyCreationException {
        // Adiciona a cláusula WHERE na consulta
        setQuery(getQuery() + " " + "\n" + ClausesSparql.WHERE.toString() + " {");

        setPrefix("ddg");

        for (String keys : queryAux.classHierarchyKey(jsonTextQuery)) {
            setArrayObjectDomain(keys);
            for (String value : queryAux.classHierarchyValue(jsonTextQuery, keys)) {
                for (TripleXML tripleXML : jPrefixes.getPropertiesForXML()) {
                    if (tripleXML.getClazz().equalsIgnoreCase(keys) && tripleXML.getProperty().equalsIgnoreCase(value)) {
                        if (getArrayObjectDomain().get(0).equalsIgnoreCase(keys)) {
                            // Adiciona a clausula OPTIONAL ao Set. Adiante terá os seus valores repassados para a variável query
                            if (queryAux.buildsOptionalKeys(jsonTextQuery, jsonTextOptional).contains(keys)
                                    && queryAux.buildsOptionalValues(jsonTextQuery, jsonTextOptional).contains(value)) {
                                setSetOptional("\n  " + ClausesSparql.OPT.toString()
                                        + " { ?" + keys + " "
                                        + tripleXML.getPrefix() + ":" + value
                                        + " ?" + keys + "_" + value + ". }");
                            } else {
                                setSetWhere("\n  ?" + keys + " "
                                        + tripleXML.getPrefix() + ":" + value
                                        + " ?" + keys + "_" + value + ".");
                            }
                        } else {
                            // Adiciona a clausula OPTIONAL ao Set. Adiante terá os seus valores repassados para a variável query
                            if (queryAux.buildsOptionalKeys(jsonTextQuery, jsonTextOptional).contains(keys)
                                    && queryAux.buildsOptionalValues(jsonTextQuery, jsonTextOptional).contains(value)) {
                                setSetOptional("\n  " + ClausesSparql.OPT.toString()
                                        + " { ?" + getArrayObjectDomain().get(0) + " "
                                        + tripleXML.getPrefix() + ":" + value
                                        + " ?" + keys + "_" + value + ". }");
                            } else {
                                setSetWhere("\n  ?" + getArrayObjectDomain().get(0) + " "
                                        + tripleXML.getPrefix() + ":" + value
                                        + " ?" + keys + "_" + value + ".");
                            }
                        }
                    }
                }
            }

            for (int i = 0; i < getArrayKeysMap().size(); i++) {
                for (int j = 0; j < getArrayKeysMap().size(); j++) {
                    for (Iterator itObjProp = buildsObjectProperty().iterator(); itObjProp.hasNext();) {
                        setTs((TripleStore) itObjProp.next());
                        if (getArrayKeysMap().get(i).equalsIgnoreCase(getTs().getDomain()) && getArrayKeysMap().get(j).equalsIgnoreCase(getTs().getRange())) {
                            queryAux.isRange(getTs().getDomain(), getTs().getRange());
                            //for (TripleXML tripleXML : jPrefixes.getPropertiesForXML()) {
                                //System.out.println(tripleXML.getClazz() + " - " + getTs().getDomain() + " - " + queryAux.findDomain());
                                //if (tripleXML.getClazz().equalsIgnoreCase(getTs().getDomain()) && tripleXML.getClazz().equalsIgnoreCase(queryAux.findDomain())) {
                                    // Verifica se uma classe é Domain e Range
                                    if (queryAux.isRange().equalsIgnoreCase(getTs().getDomain())) {
                                        setSetWhere("\n  ?" + getTs().getDomain() + "_" + queryAux.findDomain() + " "
                                                + getPrefix() + ":" + getTs().getObjectProperty()
                                                + " ?" + getTs().getRange() + "_" + getTs().getDomain() + ".");

//                                        setSetWhere("\n  ?" + getTs().getDomain() + "_" + queryAux.findDomain() + " "
//                                                + tripleXML.getPrefix() + ":" + getTs().getObjectProperty()
//                                                + " ?" + getTs().getRange() + "_" + getTs().getDomain() + ".");


                                    } else {
                                        setSetWhere("\n  ?" + getTs().getDomain() + " "
                                                + getPrefix() + ":" + getTs().getObjectProperty()
                                                + " ?" + getTs().getRange() + "_" + getTs().getDomain() + ".");

//                                        setSetWhere("\n  ?" + getTs().getDomain() + " "
//                                                + tripleXML.getPrefix() + ":" + getTs().getObjectProperty()
//                                                + " ?" + getTs().getRange() + "_" + getTs().getDomain() + ".");
                                    }
                                    getArrayObjectDomain().add(getTs().getRange() + "_" + getTs().getDomain());
                                //}
                            //}
                        }
                    }
                }
            }

            getArrayObjectDomain().remove(getArrayObjectDomain().get(0));
        }

        // Adiciona as triplas do WHERE na consulta
        for (String varWhere : getSetWhere()) {
            setQuery(getQuery() + " " + varWhere);
        }

        // Adiciona o FILTER a consulta
        if (!setFilter.isEmpty()) {
            for (String varFilter : setFilter) {
                setQuery(getQuery() + " " + "\n  " + ClausesSparql.FILTER.toString() + " { " + varFilter + " }.");
            }
        }

        // Adiciona o OPTIONAL a consulta
        if (!getSetOptional().isEmpty()) {
            for (String varOptional : getSetOptional()) {
                setQuery(getQuery() + " " + varOptional);
            }
        }
        setQuery(getQuery() + " " + "\n}");

        return getQuery();
    }
}
